package com.reader.cms.service.impl.sys;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.reader.cms.entity.sys.SysToken;
import com.reader.cms.mapper.sys.SysTokenMapper;
import com.reader.cms.service.sys.ISysTokenService;
import com.reader.core.exception.CustomException;
import com.reader.core.redis.RedisDao;
import com.reader.core.utils.CommonVariable;
import com.reader.core.utils.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @@description  服务实现类
 * @author        jiahaikun
 * @date          2018-11-01
 */
@Service
@Transactional
public class SysTokenServiceImpl extends ServiceImpl<SysTokenMapper, SysToken> implements ISysTokenService {

@Autowired
private SysTokenMapper tokenMapper;

@Autowired
private RedisDao redisDao;

    @Override
    public SysToken createToken(int userId,String loginId) {
        //同一用户重复登录会踢出以前登录过的TOKEN,确保同一loginId的token唯一
        String tokenKepPattern=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,"*");
        Set<String> keys=redisDao.getKeys(tokenKepPattern);
        for(String key :keys){
            redisDao.setExpireTime(key,0, TimeUnit.MILLISECONDS);
        }

        String accessToken=generateToken();
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,accessToken);
        Long expireDate = System.currentTimeMillis()+CommonVariable.CMS_TOKEN_EXPIRES_TIME; //token 过期时间
        SysToken token=new SysToken();
        token.setUserID(userId);
        token.setLoginId(loginId);
        token.setAccess_token(accessToken);
        token.setExpire_in(expireDate);//token 过期时间
        redisDao.save(tokenKey,token,CommonVariable.CMS_TOKEN_EXPIRES_TIME, TimeUnit.MILLISECONDS);
        return token;
    }

    @Override
    public SysToken getTokenInfoByToken(String token) {
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,"*",token);
        //设置立刻过期
        Set<String> keys=redisDao.getKeys(tokenKey);
        if(keys.size()>1){ //如果查到的KEY大于1个，则返回异常
            throw new CustomException(String.format("token{%s}不唯一",token));
        }

        for(String key :keys){
            return redisDao.getObject(key, SysToken.class);
        }
       return null;
    }

    @Override
    public void expireToken(String token) {
        expireToken(0,token);
    }

    @Override
    public void expireToken(long time, String token) {
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,"*",token);
        //设置立刻过期
        Set<String> keys=redisDao.getKeys(tokenKey);
        if(keys.size()>1){ //如果查到的KEY大于1个，则返回异常
            throw new CustomException(String.format("token{%s}不唯一",token));
        }

        for(String key :keys){
            redisDao.setExpireTime(key,time, TimeUnit.MILLISECONDS);
        }

    }

    /**
     * 生成token
     * @return
     */
    private String generateToken(){
        return IdUtils.generateUUID().replace("-", "");
    }

    @Override
    public SysToken getTokenInfoByLoginId(String loginId) {
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,"*");
        Set<String> keys=redisDao.getKeys(tokenKey);
        if(keys.size()>1){ //如果查到的KEY大于1个，则返回异常
            throw new CustomException(String.format("同一loginId{%s} 的token 不唯一%s",loginId));
        }

        for(String key :keys){
            return redisDao.getObject(key, SysToken.class);
        }

       return null ;
    }

    @Override
    public int plusRetry(String loginId) {
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,"*");
        Set<String> keys=redisDao.getKeys(tokenKey);
        SysToken sysToken=null;
        if(keys.size()>1){ //如果查到的KEY大于1个，则返回异常
            throw new CustomException(String.format("同一loginId{%s} 的token 不唯一%s",loginId));
        }

        for(String key :keys){
            sysToken=redisDao.getObject(key, SysToken.class);
        }
        if(sysToken!=null){
            sysToken.setRetryLoginCnt(sysToken.getRetryLoginCnt()+1);
            tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,sysToken.getAccess_token());
            redisDao.save(tokenKey,sysToken,CommonVariable.CMS_TOKEN_LOCK_TIME, TimeUnit.MILLISECONDS);
        }
        return sysToken.getRetryLoginCnt();
    }

    @Override
    public int initRetry(String loginId) {
        String tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,"*");
        Set<String> keys=redisDao.getKeys(tokenKey);
        SysToken sysToken=null;
        if(keys.size()>1){ //如果查到的KEY大于1个，则返回异常
            throw new CustomException(String.format("同一LoginId{s%} 的token 不唯一%s",loginId));
        }

        for(String key :keys){
            sysToken=redisDao.getObject(key, SysToken.class);
        }
        if(sysToken!=null){
            sysToken.setRetryLoginCnt(0);
            tokenKey=String.format(CommonVariable.CMS_TOKEN_KEY,loginId,sysToken.getAccess_token());
            redisDao.save(tokenKey,sysToken,CommonVariable.CMS_TOKEN_EXPIRES_TIME, TimeUnit.MILLISECONDS);
        }
        return sysToken.getRetryLoginCnt();
    }
}